home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2007 December / PCWKCD1207B.iso / Blogowanie poza sfera / Flock 1.0 beta / flock-1.0RC3.en-US.win32.exe / flock / modules / onlineFavoritesBackend.jsm < prev    next >
Text File  |  2007-10-18  |  15KB  |  451 lines

  1. // BEGIN FLOCK GPL
  2. // 
  3. // Copyright Flock Inc. 2005-2007
  4. // http://flock.com
  5. // 
  6. // This file may be used under the terms of of the
  7. // GNU General Public License Version 2 or later (the "GPL"),
  8. // http://www.gnu.org/licenses/gpl.html
  9. // 
  10. // Software distributed under the License is distributed on an "AS IS" basis,
  11. // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. // for the specific language governing rights and limitations under the
  13. // License.
  14. // 
  15. // END FLOCK GPL
  16.  
  17. var EXPORTED_SYMBOLS = ["onlineFavoritesBackend"];
  18.  
  19. const CC = Components.classes;
  20. const CI = Components.interfaces;
  21. const CR = Components.results;
  22. const CU = Components.utils;
  23.  
  24. CU.import("resource:///modules/FlockScheduler.jsm");
  25.  
  26. /**************************************************************************
  27.  * Module: Online Favorites Back End
  28.  **************************************************************************/
  29.  
  30. /* Note: This module depends on access to the following PRIVATE properties
  31.          of the services being supported:
  32.          - aService._coop
  33.          - aService._logger
  34.          - aService._c_svc
  35. */
  36.  
  37. // Bookmark stream refresh interval in seconds.
  38. const DEFAULT_REFRESH_INTERVAL = 5 * 60;
  39. const PREF_ONLINEFAVE_REFRESH_INTERVAL = "flock.favorites.online.refreshInterval";
  40.  
  41. CC["@mozilla.org/moz/jssubscript-loader;1"]
  42. .getService(CI.mozIJSSubScriptLoader)
  43. .loadSubScript("chrome://flock/content/common/flocksafe.js");
  44.  
  45.  
  46. /**************************************************************************
  47.  * Private Data and Functions
  48.  **************************************************************************/
  49.  
  50. // Helper function to assist in comparing strings.
  51. function stringify(aObj) {
  52.   if (!aObj) {
  53.     return "";
  54.   } else {
  55.     return aObj;
  56.   }
  57. }
  58.  
  59. // Helper function to assist in comparing dates.
  60. function dateify(aObj) {
  61.   if (!aObj) {
  62.     return 0;
  63.   } else {
  64.     return aObj.getTime();
  65.   }
  66. }
  67.  
  68. // Helper function to assist in comparing lists of tags.
  69. function sanitizeTags(aTagList) {
  70.   return aTagList ? aTagList.split(/[\s,]/).sort().join(",") : "";
  71. }
  72.  
  73. // Helper function to assist in comparing complete bookmarks.
  74. function bookmarks_match(bm1, bm2) {
  75.   return (bm1.private === bm2.private && /* booleans - nice and easy */
  76.           stringify(bm1.name) === stringify (bm2.name) &&
  77.           stringify(bm1.description) === stringify(bm2.description) &&
  78.           sanitizeTags(bm1.tags) === sanitizeTags(bm2.tags) &&
  79.           dateify(bm1.datevalue) === dateify(bm2.datevalue));
  80. }
  81.  
  82.  
  83. /**************************************************************************
  84.  * Online Favorites Back End Public Interface
  85.  **************************************************************************/
  86.  
  87. var onlineFavoritesBackend = {};
  88.  
  89. onlineFavoritesBackend.createAccount =
  90. function OFBE_createAccount(aService, aAccountID, aIsTransient) {
  91.   var account_urn = aService.urn + ":" + aAccountID;
  92.   var account;
  93.   if (!aService._coop.Account.exists(account_urn)) {
  94.     account = new aService._coop.Account(account_urn, {
  95.       name: aAccountID,
  96.       serviceId: aService.contractId,
  97.       service: aService._c_svc,
  98.       accountId: aAccountID,
  99.       favicon: aService.icon,
  100.       URL: aService.getUserUrl(aAccountID),
  101.       isTransient: aIsTransient,
  102.       showInSidebar: false
  103.     });
  104.     aService._coop.accounts_root.children.addOnce(account);
  105.   } else {
  106.     account = aService._coop.get(account_urn);
  107.   }
  108.  
  109.   // Create a "stream" for the online bookmarks
  110.   var bookmarks = {};
  111.   var bookmarks_urn = account_urn + ":bookmarks";
  112.   if (!aService._coop.OnlineBookmarksStream.exists(bookmarks_urn)) {
  113.     prefService = CC["@mozilla.org/preferences-service;1"]
  114.                   .getService(CI.nsIPrefBranch);
  115.     var prefRefreshInterval = DEFAULT_REFRESH_INTERVAL;
  116.     if (prefService.getPrefType(PREF_ONLINEFAVE_REFRESH_INTERVAL)) {
  117.       prefRefreshInterval = prefService.getIntPref(PREF_ONLINEFAVE_REFRESH_INTERVAL);
  118.     }
  119.  
  120.     bookmarks = new aService._coop.OnlineBookmarksStream(bookmarks_urn, {
  121.       name: aAccountID + " on " + aService.title,
  122.       userid: aAccountID,
  123.       serviceId: aService.contractId,
  124.       favicon: aService.icon,
  125.       isTransient: aIsTransient,
  126.       refreshInterval: prefRefreshInterval
  127.     });
  128.     aService._coop.onlinebookmarks_root.children.addOnce(bookmarks);
  129.   }
  130.  
  131.   // Create the "no tag" folder
  132.   var noTagFolder = new aService._coop.Folder(bookmarks.id() + ":notag", {
  133.     name: flockGetString("favorites/favorites", "flock.favs.online.noTag")
  134.   });
  135.   bookmarks.children.add(noTagFolder);
  136.  
  137.   var acct = aService.getAccount(account_urn);
  138.   return acct;
  139. };
  140.  
  141. onlineFavoritesBackend.removeAccount =
  142. function OFBE_removeAccount(aService, aAccountUrn) {
  143.   var acctCoopObj = aService._coop.get(aAccountUrn);
  144.   var parents = {};
  145.   var i;
  146.   // Next delete the bookmarks that are solely associated with this account
  147.   var bookmarks_urn = aAccountUrn + ":bookmarks";
  148.   var bmStream = aService._coop.get(bookmarks_urn);
  149.   if (bmStream) {
  150.     aService._logger.debug("found bookmark stream " + bookmarks_urn);
  151.     // Remove the Delicious Bookmarks node from its parents
  152.     parents = bmStream.getParents();
  153.     for (i = 0; i < parents.length; i++) {
  154.       parents[i].children.remove(bmStream);
  155.     }
  156.   } else {
  157.     aService._logger.debug("DID NOT find bookmark stream " + bookmarks_urn);
  158.   }
  159.   // Next remove the account from any parents it might have
  160.   parents = acctCoopObj.getParents();
  161.   for (i = 0; i < parents.length; i++) {
  162.     aService._logger.debug("removing from parent " + i);
  163.     parents[i].children.remove(acctCoopObj);
  164.   }
  165.   // kill the account node
  166.   aService._logger.debug("destroying account " + aAccountUrn);
  167.   acctCoopObj.destroy();
  168.  
  169.   // Finally, slowly delete the bookmarks
  170.   var synchronize = function OFBE_removeAccount_sync(should_yield) {
  171.     var i = 0;
  172.     var bmChildren = bmStream.children.enumerate();
  173.     while (bmChildren.hasMoreElements()) {
  174.       var tag = bmChildren.getNext();
  175.       var enum_ = tag.children.enumerate();
  176.       while (enum_.hasMoreElements()) {
  177.         var bm = enum_.getNext();
  178.         aService._logger.debug("destroying bookmark " + bm.URL);
  179.         var parents = bm.getParents();
  180.         for (var j = 0; j < parents.length; j++) {
  181.           parents[j].children.remove(bm);
  182.         }
  183.         bm.destroy();
  184.         if (should_yield()) {
  185.           yield;
  186.         }
  187.       }
  188.     }
  189.     bmStream.destroy();
  190.   };
  191.  
  192.   if (bmStream) {
  193.     FlockScheduler.schedule(null, 0.1, 10, synchronize);
  194.   }
  195. };
  196.  
  197. onlineFavoritesBackend.updateBookmark =
  198. function OFBE_updateBookmark(aService, aAccountUrn, aServerBookmark, aPrivate) {
  199.   var bookmark_urn = aAccountUrn + ":" + aServerBookmark.URL;
  200.   var localBookmark = null;
  201.   var tagList;
  202.   var i;
  203.  
  204.   // Create/update the bookmark itself
  205.   if (aService._coop.Bookmark.exists(bookmark_urn)) {
  206.     // Need to check if any modification is needed before we assert anything
  207.     localBookmark = aService._coop.get(bookmark_urn);
  208.     if (bookmarks_match(aServerBookmark, localBookmark)) {
  209.       aService._logger.debug("Unchanged on server: Ignoring "
  210.                              + aServerBookmark.URL);
  211.       return;
  212.     }
  213.     aService._logger.debug("Modified on server : Updating "
  214.                            + aServerBookmark.URL);
  215.     if (stringify(aServerBookmark.name) !== stringify(localBookmark.name)) {
  216.       localBookmark.name = aServerBookmark.name;
  217.     }
  218.     if (stringify(aServerBookmark.description) !==
  219.         stringify(localBookmark.description))
  220.     {
  221.       localBookmark.description = aServerBookmark.description;
  222.     }
  223.     if (sanitizeTags(aServerBookmark.tags) !==
  224.         sanitizeTags(localBookmark.tags))
  225.     {
  226.       localBookmark.tags = sanitizeTags(aServerBookmark.tags);
  227.       var tagenum = localBookmark.tag.enumerate();
  228.       while (tagenum.hasMoreElements()) {
  229.         var tag = tagenum.getNext();
  230.         localBookmark.tag.remove(tag);
  231.       }
  232.     }
  233.     var date = new Date();
  234.     localBookmark.LastModifiedDate = date;
  235.     localBookmark.private = aPrivate;
  236.   } else {
  237.     // New bookmark
  238.     aService._logger.debug("New on server      : Creating "
  239.                            + aServerBookmark.URL);
  240.     localBookmark = new aService._coop.Bookmark(bookmark_urn, {
  241.       URL: aServerBookmark.URL,
  242.       name: aServerBookmark.name,
  243.       description: aServerBookmark.description,
  244.       tags: aServerBookmark.tags,
  245.       datevalue: aServerBookmark.datevalue,
  246.       hash: aServerBookmark.hash,
  247.       flockType: "bookmark",
  248.       private: aPrivate,
  249.       isPollable: false
  250.     });
  251.     // bookmarks.children.add(localBookmark);
  252.   }
  253.   tagList = aServerBookmark.tags.split(/[\s,]/);
  254.   for (i = 0; i < tagList.length; i++) {
  255.     localBookmark.tag.addOnce(tagList[i]);
  256.   }
  257.   var bookmarks = aService._coop.get(aAccountUrn + ":bookmarks");
  258.   this.classifyBookmark(aService, bookmarks, localBookmark, tagList);
  259. };
  260.  
  261. onlineFavoritesBackend.classifyBookmark =
  262. function OFBE_classifyBookmark(aService, aBookmarks,
  263.                                aLocalBookmark, aTagList) {
  264.   var i;
  265.   // Delete the bookmark from the tag folders, and delete empty tags
  266.   var parents = aLocalBookmark.getParents();
  267.   while (parents.length > 0) {
  268.     var parent_ = parents.pop();
  269.     parent_.children.remove(aLocalBookmark);
  270.     if (!parent_.children.count()) {
  271.       aBookmarks.children.remove(parent_);
  272.       parent_.destroy();
  273.     }
  274.   }
  275.  
  276.   var tagFolder;
  277.   // Add the bookmark to the tag folders it should be
  278.   if ((aTagList.length === 1 && !aTagList[0].length) ||
  279.       (!aTagList.length) ||
  280.       (aTagList === [""]))
  281.   {
  282.     var noTagUrn = aBookmarks.id() + ":notag";
  283.     tagFolder = aService._coop.get(noTagUrn);
  284.     tagFolder.children.add(aLocalBookmark);
  285.   } else {
  286.     for (i = 0; i < aTagList.length; i++) {
  287.       var tagUrn = aBookmarks.id() + ":tag:" + aTagList[i];
  288.       if (aService._coop.Folder.exists(tagUrn)) {
  289.         tagFolder = aService._coop.get(tagUrn);
  290.       } else {
  291.         tagFolder = this.createTag(aService, aBookmarks, aTagList[i], tagUrn);
  292.       }
  293.       tagFolder.children.add(aLocalBookmark);
  294.     }
  295.   }
  296. };
  297.  
  298. onlineFavoritesBackend.destroyBookmark =
  299. function OFBE_destroyBookmark(aService, aAccountId, aUrl) {
  300.   var bookmark_urn = aService.urn + ":" + aAccountId + ":" + aUrl;
  301.  
  302.   if (aService._coop.Bookmark.exists(bookmark_urn)) {
  303.     var bookmarks = aService._coop.get(aService.urn + ":"
  304.                   + aAccountId + ":bookmarks");
  305.     var bookmark = aService._coop.get(bookmark_urn);
  306.  
  307.     bookmarks.children.remove(bookmark);
  308.     bookmark.destroy();
  309.   }
  310. };
  311.  
  312. onlineFavoritesBackend.updateLocal =
  313. function OFBE_updateLocal(aService, aPostsList, aLastUpdate, aAccountUrn) {
  314.   var i;
  315.   var bmEnum;
  316.   var bmEnum2;
  317.   // Update the last update time for the bookmark stream
  318.   var localBookmarks = aService._coop.get(aAccountUrn + ":bookmarks");
  319.   localBookmarks.last_update_time = aLastUpdate;
  320.  
  321.   var be = this;
  322.   var synchronize = function OFBE_updateLocal_sync(should_yield) {
  323.     var urlHash = {}; // Useful to optimize deletion
  324.  
  325.     // Create new bookmarks, or update existing bookmarks
  326.     for (i = 0; i < aPostsList.length; i++) {
  327.       if (aPostsList[i].tags === "system:unfiled") {
  328.         aPostsList[i].tags = "";
  329.       }
  330.       // To optimize deletion: put the URLs in a hash
  331.       urlHash[aPostsList[i].URL] = true;
  332.       be.updateBookmark(aService, aAccountUrn, aPostsList[i]);
  333.       if (should_yield()) {
  334.         yield;
  335.       }
  336.     }
  337.  
  338.     // Remove locally bookmarks deleted on the server
  339.     var localLength = 0;
  340.     i = 0;
  341.     bmEnum = localBookmarks.children.enumerate();
  342.     while (bmEnum.hasMoreElements()) {
  343.       var localTag = bmEnum.getNext();
  344.       bmEnum2 = localTag.children.enumerate();
  345.       while (bmEnum2.hasMoreElements()) {
  346.         var localBookmark = bmEnum2.getNext();
  347.         if (!urlHash[localBookmark.URL]) {
  348.           aService._logger.debug("Deleted on server  : Deleting "
  349.                                  + localBookmark.URL);
  350.           var parents = localBookmark.getParents();
  351.           for (var j = 0; j < parents.length; j++) {
  352.             parents[j].children.remove(localBookmark);
  353.           }
  354.           localBookmark.destroy();
  355.         }
  356.       }
  357.       if (should_yield()) {
  358.         yield;
  359.       }
  360.     }
  361.  
  362.     // Remove empty tags
  363.     bmEnum = localBookmarks.children.enumerate();
  364.     while (bmEnum.hasMoreElements()) {
  365.       var tag = bmEnum.getNext();
  366.       bmEnum2 = tag.children.enumerate();
  367.       if (!bmEnum2.hasMoreElements() &&
  368.           (tag.id() !== localBookmarks.id() + ":notag"))
  369.       {
  370.         // The tag is empty, let's delete it.
  371.         // Note: Don't delete "No Tag".
  372.         localBookmarks.children.remove(tag);
  373.         tag.destroy();
  374.       }
  375.     }
  376.   };
  377.  
  378.   FlockScheduler.schedule(null, 0.1, 10, synchronize);
  379. };
  380.  
  381. onlineFavoritesBackend.createTag =
  382. function OFBE_createTag(aService, aBookmarks, aTag, aTagUrn) {
  383.   var tagFolder = new aService._coop.Folder(aTagUrn,
  384.     { name: aTag }
  385.   );
  386.   var enum_ = aBookmarks.children.enumerate();
  387.   var found = false;
  388.   var i = 1;
  389.   enum_.getNext(); // Ignore "notag"
  390.   while (enum_.hasMoreElements() && !found) {
  391.     var currentTag = enum_.getNext();
  392.     if (aTag < currentTag.name) {
  393.       found = true;
  394.       aBookmarks.children.insertAt(tagFolder, i + 1);
  395.     }
  396.     i++;
  397.   }
  398.   if (!found) {
  399.     aBookmarks.children.add(tagFolder);
  400.   }
  401.   return tagFolder;
  402. };
  403.  
  404. onlineFavoritesBackend.updateTags =
  405. function OFBE_updateTags(aService, aAccountId, aTags) {
  406.   // Copy aTags, so we can modify it.
  407.   var tags = [];
  408.   var tag;
  409.   var i;
  410.   for (i = 0; i < aTags.length; i++) {
  411.     tags.push(aTags[i]);
  412.   }
  413.   // Remove tags no longer present.
  414.   var localBookmarks = aService._coop.get(aService.urn + ":"
  415.                      + aAccountId + ":bookmarks");
  416.   var tagenum = localBookmarks.tag.enumerate();
  417.   while (tagenum.hasMoreElements()) {
  418.     tag = tagenum.getNext();
  419.     if (tags.indexOf(tag) < 0) {
  420.       // Not in new array, so remove it.
  421.       localBookmarks.tag.remove(tag);
  422.     } else {
  423.       // Already there, remove from input so we don't try adding it again.
  424.       tags.splice(tags.indexOf(tag), 1);
  425.     }
  426.   }
  427.   // Put in the net new tags.
  428.   for (i = 0; i < tags.length; i++) {
  429.     localBookmarks.tag.addOnce(tags[i]);
  430.   }
  431. };
  432.  
  433. onlineFavoritesBackend.showNotification =
  434. function OFBE_showNotification(aMessage) {
  435.   var wm = CC["@mozilla.org/appshell/window-mediator;1"]
  436.            .getService(CI.nsIWindowMediator);
  437.   var topNavWindow = wm.getMostRecentWindow("navigator:browser");
  438.  
  439.   var nBox = topNavWindow.gBrowser.getNotificationBox();
  440.   var notification = nBox.getNotificationWithValue("favorite-error");
  441.   if (notification) {
  442.     notification.label = aMessage;
  443.   } else {
  444.     nBox.appendNotification(aMessage,
  445.                             "favorite-error",
  446.                             "chrome://browser/skin/Info.png",
  447.                             nBox.FLOCK_PRIORITY_HIGH,
  448.                             null);
  449.   }
  450. };
  451.